Register-Lib PowerShell.Configuration.Xml -InitDependencies PowerShell.Sugar

    function LoadConfigXml($path){
        [xml]$xmlinput = (Get-Content $path) 
        return $xmlinput.Configuration

    }
    
    filter ConvertTo-StringList(){ $str = $_
        if($str) {
            $str.Split("`n", [StringSplitOptions]::RemoveEmptyEntries) | % { $_.Trim() } | ? {$_}
        }
    }
    
    filter SetConfigProperty($Name, $Value){ $config = $_
        $config | Add-Member NoteProperty -Name:$Name -Value:$Value -Force
    }
    
    filter SetConfigProperties($Hash){ $config = $_
        $hash.Keys | % { $name = $_; $config | SetConfigProperty -name:$Name -value:($hash[$name]) }  
        $config
    }
    
    function ProcessXmlConfigProperties($source,$target, [switch] $includeRawXml, $NodeType){
        if(!$target) { $target = New-Object PSObject }
        $source | gm -MemberType Property | % { $prop = $_
            $propName = $prop.Name
            $private:node = $null
            $private:values = ($source | : -ExpandProperty $prop.Name)
            if($private:values){
                $private:values = $private:values | % { $value = $_
                    if($value -is [System.Xml.XmlElement]){
                        $private:node = $value
                        $private:value = $node.InnerText
                    }
                    $private:value = $value | ConvertTo-StringList
                    if($node){
                        $private:format = $node.Format | ?? 'XML'
                        switch($format) {
                            'CSV' { $value = $value | ConvertFrom-Csv }
                            'XML' { $value = ProcessXmlConfigProperties $node -includeRawXml:$includeRawXml -NodeType:($node.Type)}
                        }
                        
                    }
                    $value
                }                
            }
            if($NodeType -eq 'List'){
                $target = $values | Add-Member NoteProperty -Name NodeType -Value:$PropName -PassThru
            }
            else { 
                $target | Add-Member NoteProperty -Name:$propName -Value:$values
            }
        }
        if($includeRawXml){
            $target| AddConfigProperty RawXml $source
        }
        $target
    }

    function GetConfigObject($configXml){
        
        $config = ProcessXmlConfigProperties $configXml
        $config | Add-Member -MemberType ScriptMethod -Name "SetProperty" -Value { SetConfigProperty $args[0] $args[1]  }
        $config
        
    }

    function LoadConfig($path) {
    
    $global:configXml = LoadConfigXml $path
    $configObj = GetConfigObject $configXml

    return $configObj
}